home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume6 / connect4 < prev    next >
Encoding:
Internet Message Format  |  1989-07-06  |  40.8 KB

  1. Path: uunet!tektronix!tekgen!tekred!games
  2. From: games@tekred.CNA.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v06i051:  connect4 - connect four opponent (you vs the computer)
  5. Message-ID: <3887@tekred.CNA.TEK.COM>
  6. Date: 26 Apr 89 18:18:27 GMT
  7. Sender: billr@tekred.CNA.TEK.COM
  8. Lines: 1517
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: speedboat jones <tcjones@watdragon.waterloo.edu>
  12. Posting-number: Volume 6, Issue 51
  13. Archive-name: connect4
  14.  
  15. [from the author:]
  16. [[Hi there. Lots of people have asked about Connect Four here in the past
  17. (or so it seems). Some months ago I wrote this Connect Four opponent
  18. (i.e. you against the machine) and intended to clean it up alot before
  19. ever posting it. Anyway now I'm leaving the net world and so I thought
  20. I'd let it out. Caveat emptor and all that.
  21.  
  22. This should compile just fine on BSD with curses, others will have to
  23. make some changes though. See the README and Install files for
  24. information.
  25.  
  26. Terry Jones]]
  27. #! /bin/sh
  28. # This is a shell archive.  Remove anything before this line, then unpack
  29. # it by saving it into a file and typing "sh file".  To overwrite existing
  30. # files, type "sh file -c".  You can also feed this as standard input via
  31. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  32. # will see the following message at the end:
  33. #        "End of archive 1 (of 1)."
  34. # Contents:  README MANIFEST Install Makefile c4.c c4.h screen.c
  35. #   tables.h types.h
  36. # Wrapped by billr@saab on Wed Apr 26 11:16:15 1989
  37. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  38. if test -f 'README' -a "${1}" != "-c" ; then 
  39.   echo shar: Will not clobber existing file \"'README'\"
  40. else
  41. echo shar: Extracting \"'README'\" \(2266 characters\)
  42. sed "s/^X//" >'README' <<'END_OF_FILE'
  43. XREADME.
  44. X
  45. X
  46. XThis is a Connect Four opponent. It was written under BSD4.3 and uses
  47. Xcurses.  Modifications to make it work on other Unices should be
  48. Xrelatively minor - I can think of perhaps 4 or 5 things that would need
  49. Xdoing.
  50. X
  51. XI am a little hesitant about releasing this now as it is far from what
  52. XI would call a finished thing and the code is ugly. It came about after
  53. Xa few hours thinking about how I could write such a thing (data
  54. Xstructures and strategy and so forth) and then one night of hacking to
  55. Xget something working. Since then it has been through several revisions
  56. Xof strategy, but I still consider it to be missing at least one ability
  57. Xthat humans seem to employ when playing. I intend to add this, but not
  58. Xin the immediate future.
  59. X
  60. XI am also hesitant about putting this into widespread distribution as
  61. XConnect Four is undoubtedly a trade mark or some such of Milton Bradley
  62. Xand I don't want to be woken up by phone calls from their lawyers.
  63. X
  64. XI just took another look at all the code etc and I'm really not very
  65. Xhappy with it. Oh well. Flames meekly accepted - as long as you let me
  66. Xsay "I already knew that..." :-)
  67. X
  68. XI'm happy to discuss strategies and improvements you might like to
  69. Xsuggest. I'd also be happy to see this code developed further, but at
  70. Xthe same time feel a little possessive about it :-( But, since I am too
  71. Xbusy to do anything more for the present, you have permission to do
  72. Xanything with this code and there is no real need to consult me.
  73. X
  74. XThere are very few comments in the code. I am planning to spend quite a
  75. Xfew hours adding some before I lay this to rest and get back to my
  76. Xschoolwork - just so that when I return to it in a year (or whenever) I
  77. Xwon't get that sinking feeling of not understanding one's own code
  78. Xanymore.  Or something like that. 
  79. X
  80. XAbove all - have fun etc etc. See the file 'Install' for instructions on
  81. Xgetting this up and going.
  82. X
  83. XRegards,
  84. XTerry Jones
  85. X
  86. XDepartment Of Computer Science,  University Of Waterloo     
  87. XWaterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674       
  88. XUUCP:                    ...!watmath!watdragon!tcjones      
  89. XCSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}  
  90. XBITNET:                  tcjones@WATER.bitnet               
  91. XCanadian domain:         tcjones@dragon.uwaterloo.ca
  92. END_OF_FILE
  93. if test 2266 -ne `wc -c <'README'`; then
  94.     echo shar: \"'README'\" unpacked with wrong size!
  95. fi
  96. # end of 'README'
  97. fi
  98. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  99.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  100. else
  101. echo shar: Extracting \"'MANIFEST'\" \(393 characters\)
  102. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  103. X   File Name        Archive #    Description
  104. X-----------------------------------------------------------
  105. X Install                    1    
  106. X MANIFEST                   1    This shipping list
  107. X Makefile                   1    
  108. X README                     1    
  109. X c4.c                       1    
  110. X c4.h                       1    
  111. X screen.c                   1    
  112. X tables.h                   1    
  113. X types.h                    1    
  114. END_OF_FILE
  115. if test 393 -ne `wc -c <'MANIFEST'`; then
  116.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  117. fi
  118. # end of 'MANIFEST'
  119. fi
  120. if test -f 'Install' -a "${1}" != "-c" ; then 
  121.   echo shar: Will not clobber existing file \"'Install'\"
  122. else
  123. echo shar: Extracting \"'Install'\" \(2209 characters\)
  124. sed "s/^X//" >'Install' <<'END_OF_FILE'
  125. XInstall
  126. X
  127. XIf you are running BSD then lucky for you! Just type make and it should
  128. Xcompile ok. If not then you'll have to make some fixes. If you can't
  129. Xfigure out what they are then I may be willing to help - send
  130. Xcompiler messages etc and I will try and make it work on a system5 or
  131. Xultrix or dynix machine here. I am only able to give limited support
  132. Xbecause I don't have alot of time for this stuff during term.
  133. X
  134. XA few things to note are....
  135. X
  136. XIf SCOREFILE is not defined in the Makefile or header file,
  137. Xc4 should be chmod'd to 4511 and will keep a log in the home directory
  138. Xof the file's owner. The log will show the results of every game that
  139. Xis played. This is very useful for looking for bugs and finding out
  140. Xwhat sort of things the game does wrong in an attempt to improve its
  141. Xstrategy etc. There is a debug option available that writes a file
  142. Xcalled 'debug' in the current directory.  (You need to change 'wizard'
  143. Xin c4.c if you wish to use debugging - you shouldn't have to).  There
  144. Xis alot of output and so you can toggle debug on and off using a 'd'
  145. Xwhilst playing. The debug on/off routines check to see that your userid
  146. Xis 'tcjones' so you will probably want to change that. All debugging
  147. Xprintfs are done with the DP #define - which will eventually vanish if
  148. Xthis ever gets released properly.
  149. X
  150. XAlso there is a char *[] table called 'experts' in tables.h. If a
  151. Xuserid in this table is playing, it will not ask whether help is
  152. Xrequired. This also I will change if ever I rewrite this thing - it
  153. Xshould check the scorefile to see if this person has played before.
  154. X
  155. XThere is a -S option to list the scorefile. I tend to find that people
  156. Xare less willing to play the game if they know that others can look at
  157. Xtheir results (hence S not s). I plan to make this better too - so that
  158. Xyou can ask for the scores for a particular person etc.
  159. X
  160. XThere is a -1 option to say "I want to go first" and a -2 option to say
  161. X"I want to go second".
  162. X
  163. XThere are MANY things I want to add and change. This grew out of a
  164. Xsocket based program that let one person play another, but that has
  165. Xdisappeared. I'd like to put it back. I'd like to make it possible to
  166. Xwithdraw moves, to save/restore games and other things.
  167. X
  168. XTerry
  169. END_OF_FILE
  170. if test 2209 -ne `wc -c <'Install'`; then
  171.     echo shar: \"'Install'\" unpacked with wrong size!
  172. fi
  173. # end of 'Install'
  174. fi
  175. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  176.   echo shar: Will not clobber existing file \"'Makefile'\"
  177. else
  178. echo shar: Extracting \"'Makefile'\" \(235 characters\)
  179. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  180. X# Makefile for c4
  181. X
  182. XCFLAGS = -g #-DSCOREFILE=\"/usr/games/lib/c4.scores\" 
  183. XCURSES = -lcurses -ltermcap
  184. X
  185. Xc4 : c4.o screen.o c4.h tables.h types.h
  186. X    cc $(CFLAGS) -o c4 c4.o screen.o $(CURSES)
  187. X
  188. Xscreen.o : c4.h
  189. X
  190. Xc4.o : c4.h tables.h types.h
  191. END_OF_FILE
  192. if test 235 -ne `wc -c <'Makefile'`; then
  193.     echo shar: \"'Makefile'\" unpacked with wrong size!
  194. fi
  195. # end of 'Makefile'
  196. fi
  197. if test -f 'c4.c' -a "${1}" != "-c" ; then 
  198.   echo shar: Will not clobber existing file \"'c4.c'\"
  199. else
  200. echo shar: Extracting \"'c4.c'\" \(18926 characters\)
  201. sed "s/^X//" >'c4.c' <<'END_OF_FILE'
  202. X/*
  203. X * c4.h - Connect Four game using curses.
  204. X *
  205. X *
  206. X * Terry Jones. December 28, 1988.
  207. X *
  208. X *     Department Of Computer Science,  University Of Waterloo
  209. X *     Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
  210. X *     UUCP:                    ...!watmath!watdragon!tcjones
  211. X *     CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
  212. X *     BITNET:                  tcjones@WATER.bitnet
  213. X *     Canadian domain:         tcjones@dragon.uwaterloo.ca
  214. X *
  215. X */
  216. X
  217. X#include <stdio.h>
  218. X#include <sys/types.h>
  219. X#include <ctype.h>
  220. X#include <pwd.h>
  221. X#include <sys/time.h>
  222. X#include <sys/file.h>
  223. X#include <sys/param.h>
  224. X#include "c4.h"
  225. X#include "types.h"
  226. X#include "tables.h"
  227. X
  228. X#define DP if (d) fprintf
  229. X#define DD if (d)
  230. X#ifndef MAXHOSTNAMELEN
  231. X#define MAXHOSTNAMELEN 64    /* from sys/param.h on vanilla 4.3bsd */
  232. X#endif
  233. X
  234. Xwin_list_t win_list;
  235. Xboard_t board;
  236. Xint moves_played = 0;
  237. Xchar *myname;
  238. Xu_char game_record[SQUARES];
  239. XFILE *scorefile;
  240. XFILE *d = NULL;
  241. XFILE *save = NULL;
  242. Xchar *u_name = "Bozo";
  243. Xchar *version = "3.2";
  244. Xchar *release_date = "8pm, January 1st, 1988";
  245. Xint turn = GAME_OVER;
  246. Xint first;
  247. Xchar *wizard = "tcjones";
  248. X
  249. Xmain(argc, argv, envp)
  250. Xint argc;
  251. Xchar **argv;
  252. Xchar **envp;
  253. X{
  254. X    register int move;
  255. X    register int square;
  256. X    register int winner = DRAW;
  257. X    int temp;
  258. X
  259. X    envmesg(envp, "Connect Four");
  260. X    do_args(argc, argv);
  261. X    open_scorefile("a");
  262. X    ask_help();
  263. X    first = turn = turn == GAME_OVER ? ask_turn() : turn;
  264. X    init_win_list_t(&win_list);
  265. X    init_board_t(&board);
  266. X    init_screen();
  267. X    accept_move(turn);
  268. X
  269. X    for (;;){
  270. X        if (moves_played == SQUARES){
  271. X            turn = GAME_OVER;
  272. X        }
  273. X
  274. X        DP(d, "\n<<< M O V E  =  %d >>>\n", moves_played + 1);
  275. X
  276. X        if (turn == GAME_OVER) break;
  277. X
  278. X        if (turn == THEIRS){
  279. X            move = get_move();
  280. X        }
  281. X        else{
  282. X            move = think_of_fucking_clever_move();
  283. X        }
  284. X
  285. X        square = update_column(move);
  286. X
  287. X        if (square < 0){
  288. X            bell();
  289. X            report("That column is full!");
  290. X            if (turn == OURS){
  291. X                winner = CONFUSED;
  292. X                turn = GAME_OVER;
  293. X                report("column %2d, square %2d", move, square);
  294. X            }
  295. X            accept_move(turn);
  296. X            continue;
  297. X        }
  298. X
  299. X        fill_column(move, turn);
  300. X        show_move(move, turn);
  301. X
  302. X        update_game_record(move);
  303. X        update_board(&board, square, turn);
  304. X        update_win_list(&win_list, square, turn);
  305. X        if ((temp = count(&win_list, (u_char) 4, turn))){
  306. X            DP(d, "Temp from count is %d\n", temp);
  307. X            winner = turn;
  308. X            turn = GAME_OVER;
  309. X        }
  310. X        else{
  311. X            turn = turn == OURS ? THEIRS : OURS;
  312. X        }
  313. X    }
  314. X    plot_finish();
  315. X    print_game_record(winner);
  316. X    goodbye();
  317. X}
  318. X
  319. Xvoid
  320. Xinit_win_list_t(w_list)
  321. Xwin_list_t *w_list;
  322. X{
  323. X    register int i;
  324. X
  325. X    for (i = 0; i < WINS; i++){
  326. X        w_list->us[i] = w_list->them[i] = (u_char) 0;
  327. X    }
  328. X}
  329. X
  330. Xvoid
  331. Xinit_board_t(bd)
  332. Xboard_t *bd;
  333. X{
  334. X    register int i;
  335. X
  336. X    for (i = 0; i < SQUARES; i++){
  337. X            bd->square[i] = EMPTY;
  338. X    }
  339. X}
  340. X
  341. X
  342. Xvoid
  343. Xprint_in_what_wins()
  344. X{
  345. X    register int i;
  346. X    for (i = 0; i < SQUARES; i++){
  347. X        int index = cum_index[i];
  348. X        printf("Sq %2d (offset = %3d) :", i, index);
  349. X        while (in_what_wins[index] != (u_char) -1){
  350. X            printf(" %d", in_what_wins[index++]);
  351. X        }
  352. X        printf("\n");
  353. X    }
  354. X}
  355. X
  356. X
  357. Xint
  358. Xget_move()
  359. X{
  360. X    register int move;
  361. X
  362. X    get: move = getchar();
  363. X
  364. X    switch(move){
  365. X
  366. X        /* COLUMN # */
  367. X        case '0': case '1': case '2': case '3': case '4': case '5': case '6':{
  368. X            return move - '0';
  369. X        }
  370. X
  371. X        /* QUIT */
  372. X        case 'q' :
  373. X        case 'x' :{
  374. X            print_game_record(QUIT);
  375. X            plot_finish();
  376. X            printf("Chicken...\n");
  377. X            goodbye();
  378. X        }
  379. X
  380. X        case 'v':{
  381. X            report("Version %s. Released %s", version, release_date);
  382. X            accept_move(turn);
  383. X            goto get;
  384. X        }
  385. X
  386. X        /* DEBUG */
  387. X        case 'd':{
  388. X            if (d)
  389. X                debug_off();
  390. X            else
  391. X                debug_on();
  392. X            goto get;
  393. X        }
  394. X
  395. X        /* CONTROL L (redraw screen) */
  396. X        case 0xc:{
  397. X            register int i;
  398. X            plot_screen();
  399. X            reset_row_levels();
  400. X            turn = first;
  401. X            for (i = 0; i < moves_played; i++){
  402. X                fill_column(game_record[i], turn);
  403. X                turn = turn == OURS ? THEIRS : OURS;
  404. X            }
  405. X            accept_move(turn);
  406. X            goto get;
  407. X        }
  408. X
  409. X        /* RUBBISH */
  410. X        default:{
  411. X            goto get;
  412. X        }
  413. X    }
  414. X}
  415. X
  416. Xint
  417. Xask_turn()
  418. X{
  419. X    char line[128];
  420. X    register char *cp;
  421. X
  422. X    printf("Would you like to go first? (yes/no) -> ");
  423. X    if (!gets(line)){
  424. X        plot_finish();
  425. X        fprintf(stderr, "Could not read input line.\n");
  426. X        goodbye();
  427. X    }
  428. X
  429. X    cp = line;
  430. X    while (*cp == ' ' || *cp == '\t') cp++;
  431. X
  432. X    if (*cp == 'n' || *cp == 'N')
  433. X        return OURS;
  434. X    return THEIRS;
  435. X}
  436. X
  437. Xint
  438. Xupdate_column(col)
  439. Xint col;
  440. X{
  441. X    int square = next_in_col[col];
  442. X    next_in_col[col] -= 7;
  443. X    return square;
  444. X}
  445. X
  446. Xvoid
  447. Xupdate_game_record(move)
  448. Xint move;
  449. X{
  450. X    game_record[moves_played] = move;
  451. X    moves_played++;
  452. X}
  453. X
  454. Xvoid
  455. Xprint_game_record(winner)
  456. Xint winner;
  457. X{
  458. X    register int i;
  459. X    char host[MAXHOSTNAMELEN];
  460. X    char *win_str = "won";
  461. X    extern char *date();
  462. X
  463. X    bell();
  464. X    switch (winner){
  465. X        case OURS:{
  466. X            printf("I won after %d moves.\n", moves_played);
  467. X            break;
  468. X        }
  469. X        case THEIRS:{
  470. X            printf("I lost after %d moves.\n", moves_played);
  471. X            win_str = "lost";
  472. X            break;
  473. X        }
  474. X        case QUIT:{
  475. X            win_str = "quit";
  476. X            break;
  477. X        }
  478. X        case DRAW:{
  479. X            printf("The game is a draw!\n");
  480. X            win_str = "drew";
  481. X            break;
  482. X        }
  483. X        default:
  484. X        case CONFUSED:{
  485. X            win_str = "confused";
  486. X        }
  487. X    }
  488. X
  489. X    if (gethostname(host, sizeof(host)) == -1){
  490. X        host[0] = '\0';
  491. X        strcat(host, "Unknown");
  492. X    }
  493. X
  494. X    if (flock(fileno(scorefile), LOCK_EX) == -1){
  495. X        fprintf(stderr, "Could not lock scorefile!\n");
  496. X        return;
  497. X    }
  498. X
  499. X    if (fseek(scorefile, 0L, 2) == -1){
  500. X        fprintf(stderr, "Could not unlock scorefile!\n");
  501. X        if (flock(fileno(scorefile), LOCK_UN) == -1){
  502. X            fprintf(stderr, "Could not unlock scorefile!\n");
  503. X        }
  504. X        return;
  505. X    }
  506. X
  507. X    fprintf(scorefile, "Opponent   : %s@%s\n", u_name, host);
  508. X    fprintf(scorefile, "Date       : %s [version %s]\n", date(), version);
  509. X    fprintf(scorefile, "Result     : %s\n", win_str);
  510. X    fprintf(scorefile, "First Move : %s\n", first == OURS ? "Me" : "Them");
  511. X    fprintf(scorefile, "Moves      : %d\n", moves_played);
  512. X    fprintf(scorefile, "Record     : ");
  513. X
  514. X    for (i = 0; i < moves_played && i < 21; i++){
  515. X        fprintf(scorefile, "%d ", game_record[i]);
  516. X    }
  517. X    if (moves_played > 21)
  518. X        fprintf(scorefile, "\n             ");
  519. X    for (i = 21; i < moves_played; i++){
  520. X        fprintf(scorefile, "%d ", game_record[i]);
  521. X    }
  522. X    fprintf(scorefile, "\n\n");
  523. X
  524. X    if (flock(fileno(scorefile), LOCK_UN) == -1){
  525. X        fprintf(stderr, "Could not unlock scorefile!\n");
  526. X        return;
  527. X    }
  528. X}
  529. X
  530. Xvoid
  531. Xupdate_board(bd, sq, whose)
  532. Xboard_t *bd;
  533. Xint sq;
  534. Xint whose;
  535. X{
  536. X    bd->square[sq] = whose;
  537. X}
  538. X
  539. Xint
  540. Xupdate_win_list(w_list, sq, whose)
  541. Xwin_list_t *w_list;
  542. Xint sq;
  543. Xint whose;
  544. X{
  545. X    /*
  546. X     * Update the win list specified by 'whose' and return a measure of
  547. X     * the value of this move.
  548. X     */
  549. X    register int index = (int) cum_index[sq];
  550. X    register u_char *my_list;
  551. X    register u_char *their_list;
  552. X    register int goodness = 0;
  553. X    register int win;
  554. X    int a_good[5];
  555. X    int d_good[5];
  556. X    int i;
  557. X
  558. X    for (i = 0; i < 5; i++){
  559. X        a_good[i] = attack_good[i];
  560. X        d_good[i] = defend_good[i];
  561. X    }
  562. X
  563. X    if (whose == OURS){
  564. X        my_list = w_list->us;
  565. X        their_list = w_list->them;
  566. X    }
  567. X    else{
  568. X        my_list = w_list->them;
  569. X        their_list = w_list->us;
  570. X    }
  571. X
  572. X    DP(d, "\t\tUpdate for square %d, turn = %d\n", sq, turn);
  573. X    while((win = (int)in_what_wins[index]) != (u_char) -1){
  574. X
  575. X        if (their_list[win] == 0){
  576. X            /* We just put something into a win in which they have none. */
  577. X            goodness += a_good[my_list[win] + 1];
  578. X            DP(d, "\t\tmake a %d in win %d", my_list[win] + 1, win);
  579. X            DP(d, "\t\tgood+=%d goodness=%d\n", a_good[my_list[win] + 1],
  580. X                goodness);
  581. X            if (my_list[win])
  582. X                a_good[my_list[win] + 1] = 0;
  583. X        }
  584. X        else if (my_list[win] == 0){
  585. X            /* We just closed off a win for them. */
  586. X            goodness += d_good[their_list[win] + 1];
  587. X            DP(d, "\t\tstop a %d in win %d", their_list[win] + 1, win);
  588. X            DP(d, "\t\tgood+=%d goodness=%d\n", d_good[their_list[win]+1],
  589. X                goodness);
  590. X            if (their_list[win])
  591. X                d_good[their_list[win] + 1] = 0;
  592. X        }
  593. X        else{
  594. X            DP(d, "\t\tNothing for win %d\n", win);
  595. X        }
  596. X
  597. X        my_list[win]++;
  598. X        index++;
  599. X    }
  600. X    return goodness;
  601. X}
  602. X
  603. Xvoid
  604. Xprint_board(bd, f)
  605. Xboard_t *bd;
  606. XFILE *f;
  607. X{
  608. X    register int row = 0;
  609. X    register int col = 0;
  610. X
  611. X    fprintf(f, "\t 0123456\n");
  612. X
  613. X    for (row = 0; row < ROWS; row++){
  614. X        fprintf(f, "\t%d", row);
  615. X
  616. X        for (col = 0; col < COLUMNS; col++){
  617. X
  618. X            switch(bd->square[row * COLUMNS + col]){
  619. X                case OURS:{
  620. X                    fprintf(f, OUR_SYM);
  621. X                    break;
  622. X                }
  623. X                case THEIRS:{
  624. X                    fprintf(f, THEIR_SYM);
  625. X                    break;
  626. X                }
  627. X                case EMPTY:{
  628. X                    fprintf(f, BLANK_SYM);
  629. X                    break;
  630. X                }
  631. X                default:{
  632. X                    fprintf(f, "fucking ugh! board screwup\n");
  633. X                    break;
  634. X                }
  635. X            }
  636. X        }
  637. X
  638. X        fprintf(f, "%d\n", row);
  639. X    }
  640. X    fprintf(f, "\t 0123456\n");
  641. X}
  642. X
  643. Xvoid
  644. Xgoodbye()
  645. X{
  646. X    exit(1);
  647. X}
  648. X
  649. Xint
  650. Xthink_of_fucking_clever_move()
  651. X{
  652. X    register int i;
  653. X    register int j;
  654. X    register int k;
  655. X    win_list_t tmp_win_i;
  656. X    win_list_t tmp_win_j;
  657. X    win_list_t tmp_win_k;
  658. X    int tmp_cols_i[COLUMNS];
  659. X    int tmp_cols_j[COLUMNS];
  660. X    int col_values_i[COLUMNS];
  661. X    int col_values_j[COLUMNS];
  662. X    int col_values_k[COLUMNS];
  663. X    int max_i;
  664. X    int best_col;
  665. X    board_t tmp_board_i;
  666. X    board_t tmp_board_j;
  667. X    board_t tmp_board_k;
  668. X
  669. X    for (i = 0; i < COLUMNS; i++){
  670. X        col_values_i[i] = 0;
  671. X    }
  672. X
  673. X    DP(d, "CLEVER MOVE... board looks like\n");
  674. X    DD print_board(&board, d);
  675. X    DP(d, "---------------------------------\n");
  676. X
  677. X    for (i = 0; i < COLUMNS; i++){
  678. X
  679. X        register int max_j;
  680. X
  681. X        DP(d, "my column %d\n", i);
  682. X
  683. X        if (next_in_col[i] < 0){
  684. X        DP(d, "my column %d is full\n", i);
  685. X            continue;
  686. X        }
  687. X
  688. X        tmp_win_i = win_list;
  689. X        tmp_board_i = board;
  690. X
  691. X        update_board(&tmp_board_i, next_in_col[i], OURS);
  692. X        DP(d, "Updated board...\n");
  693. X        DD print_board(&tmp_board_i, d);
  694. X        col_values_i[i] = update_win_list(&tmp_win_i, next_in_col[i], OURS);
  695. X
  696. X        if (col_values_i[i] >= attack_good[4])
  697. X            return i;
  698. X
  699. X        DP(d, "my column %d gets value %d after update\n", i, col_values_i[i]);
  700. X
  701. X        for (j = 0; j < COLUMNS; j++){
  702. X            tmp_cols_i[j] = next_in_col[j];
  703. X            col_values_j[j] = 0;
  704. X        }
  705. X        tmp_cols_i[i] -= 7;
  706. X
  707. X        DP(d, "Temporary columns for inner loop... ");
  708. X        for (j = 0; j < COLUMNS; j++){
  709. X            DP(d, "%2d ", tmp_cols_i[j]);
  710. X        }
  711. X        DP(d, "\n");
  712. X
  713. X        for (j = 0; j < COLUMNS; j++){
  714. X
  715. X            register int max_k;
  716. X
  717. X            DP(d, "\this column %d\n", j);
  718. X            if (tmp_cols_i[j] < 0){
  719. X                DP(d, "\this column %d is full\n", j);
  720. X                continue;
  721. X            }
  722. X
  723. X            tmp_win_j = tmp_win_i;
  724. X            tmp_board_j = tmp_board_i;
  725. X
  726. X            update_board(&tmp_board_j, tmp_cols_i[j], THEIRS);
  727. X            DP(d, "\tUpdated board...\n");
  728. X            DD print_board(&tmp_board_j, d);
  729. X            col_values_j[j] = update_win_list(&tmp_win_j, tmp_cols_i[j], THEIRS);
  730. X
  731. X            if (col_values_j[j] >= attack_good[4]){
  732. X                /* He gets a win if we do column i. fudge the value up. */
  733. X                col_values_j[j] += (attack_good[4] << 1);
  734. X            }
  735. X
  736. X            DP(d, "\this column %d gets value %d after update\n", j, col_values_j[j]);
  737. X            for (k = 0; k < COLUMNS; k++){
  738. X                tmp_cols_j[k] = tmp_cols_i[k];
  739. X                col_values_k[k] = 0;
  740. X            }
  741. X            tmp_cols_j[j] -= 7;
  742. X            for (k = 0; k < COLUMNS; k++){
  743. X
  744. X                if (tmp_cols_j[k] < 0){
  745. X                    continue;
  746. X                }
  747. X
  748. X                tmp_win_k = tmp_win_j;
  749. X                tmp_board_k = tmp_board_j;
  750. X                update_board(&tmp_board_k, tmp_cols_j[k], OURS);
  751. X                col_values_k[k] = update_win_list(&tmp_win_k, tmp_cols_j[k], OURS);
  752. X            }
  753. X            max_k = 0;
  754. X            for (k = 0; k < COLUMNS; k++){
  755. X                if (col_values_k[k] > max_k){
  756. X                    max_k = col_values_k[k];
  757. X                }
  758. X            }
  759. X
  760. X            col_values_j[j] -= max_k;
  761. X        }
  762. X
  763. X        max_j = 0;
  764. X        for (j = 0; j < COLUMNS; j++){
  765. X            if (col_values_j[j] > max_j){
  766. X                max_j = col_values_j[j];
  767. X            }
  768. X        }
  769. X        DP(d, "the maximum reply for him has value %d\n", max_j);
  770. X
  771. X        col_values_i[i] -= max_j;
  772. X        DP(d, "column %d reduced by %d to %d\n", i, max_j, col_values_i[i]);
  773. X    }
  774. X
  775. X    DP(d, "All of my options have been calculated... ");
  776. X    for (j = 0; j < COLUMNS; j++){
  777. X        DP(d, "%2d ", col_values_i[j]);
  778. X    }
  779. X    DP(d, "\n");
  780. X
  781. X    best_col = -1;
  782. X    max_i = -4 * attack_good[4];
  783. X    for (i = 0; i < COLUMNS; i++){
  784. X        if (next_in_col[i] >= 0 && col_values_i[i] > max_i){
  785. X            max_i = col_values_i[i];
  786. X            best_col = i;
  787. X        }
  788. X    }
  789. X    DP(d, "The best column is %d\n", best_col);
  790. X    DP(d, "Returning.\n\n\n", best_col);
  791. X
  792. X    if (best_col == -1){
  793. X        print_game_record(CONFUSED);
  794. X        plot_finish();
  795. X        printf("Heavens above, I'm confused... Sorry.\n");
  796. X        goodbye();
  797. X
  798. X    }
  799. X
  800. X    return best_col;
  801. X}
  802. X
  803. X
  804. Xvoid
  805. Xask_help()
  806. X{
  807. X    char line[128];
  808. X    char *cp;
  809. X    struct passwd *pwd;
  810. X    register int i;
  811. X
  812. X    
  813. X    if (!(pwd = getpwuid(getuid())))
  814. X        return;
  815. X
  816. X    u_name = pwd->pw_name;
  817. X
  818. X    for (i = 0; experts[i][0]; i++){
  819. X        if (!strcmp(u_name, experts[i])){
  820. X            return;
  821. X        }
  822. X    }
  823. X
  824. X    printf("Do you need help (n/y)? -> ");
  825. X    if (!gets(line)){
  826. X        fprintf(stderr, "Could not read input line\n");
  827. X        goodbye();
  828. X    }
  829. X
  830. X    cp = line;
  831. X
  832. X    while (*cp == ' ' || *cp == '\t') cp++;
  833. X
  834. X    if (*cp != 'y' && *cp != 'Y') return;
  835. X    print_help();
  836. X}
  837. X
  838. Xvoid
  839. Xprint_help()
  840. X{
  841. X    fprintf(stderr, "The columns are numbered 0 to 6 from left to right.\n");
  842. X    fprintf(stderr, "To enter a move just type the column number.\n");
  843. X    fprintf(stderr, "My tiles will be the X'd ones.\n");
  844. X    fprintf(stderr, "'q' or 'x' on your move will quit the game early.\n");
  845. X    fprintf(stderr, "^L will redraw the screen.\n");
  846. X    fprintf(stderr, "Invoke with -h for this help, -1 to go 1st, -2 to go 2nd.\n");
  847. X}
  848. X
  849. X
  850. Xvoid
  851. Xopen_scorefile(mode)
  852. Xchar *mode;
  853. X{
  854. X    struct passwd *pwd;
  855. X    char file[256];
  856. X
  857. X#ifndef SCOREFILE
  858. X    pwd = getpwuid(geteuid());
  859. X    sprintf(file, "%s/.connect4rc", pwd->pw_dir);
  860. X#else
  861. X    strcpy(file, SCOREFILE);
  862. X#endif
  863. X
  864. X    scorefile = fopen(file, mode);
  865. X    if (!scorefile){
  866. X        fprintf(stderr, "Can't open score file (%s)\n", file);
  867. X        exit(1);
  868. X    }
  869. X
  870. X    if (setuid(getuid())){
  871. X        fprintf(stderr, "Can't set permissions correctly!  Exiting!\n");
  872. X        exit(0);
  873. X    }
  874. X
  875. X    if (setgid(getgid())){
  876. X        fprintf(stderr, "Can't set group id correctly!  Exiting!\n");
  877. X        exit(0);
  878. X    }
  879. X}
  880. X
  881. Xchar *
  882. Xdate()
  883. X{
  884. X    /* return pointer to NULL terminated date string */
  885. X
  886. X    extern char *index();
  887. X    static char time[26];
  888. X    struct timeval v;
  889. X    struct timezone z;
  890. X    char *nl;
  891. X
  892. X    gettimeofday(&v, &z);
  893. X    sprintf(time,"%s", ctime(&v.tv_sec));
  894. X
  895. X    if ((nl = index(time, '\n')) == NULL){
  896. X        fprintf(stderr,"date: ctime returned non-newline terminated string.\n");
  897. X        exit(1);
  898. X    }
  899. X
  900. X    *nl = '\0';
  901. X    return time;
  902. X}
  903. X
  904. Xvoid
  905. Xdo_args(argc, argv)
  906. Xint argc;
  907. Xchar **argv;
  908. X{
  909. X    myname = argv[0];
  910. X    argv++;
  911. X
  912. X    while (--argc){
  913. X        if (**argv == '-'){
  914. X            switch (argv[0][1]){
  915. X                case 'S':{
  916. X                    do_scores();
  917. X                    goodbye();
  918. X                }
  919. X                case 'h':{
  920. X                    print_help();
  921. X                    goodbye();
  922. X                }
  923. X                case 'v':{
  924. X                    printf("Version %s\n", version);
  925. X                    printf("Released : %s\n", release_date);
  926. X                    goodbye();
  927. X                }
  928. X                case '1':{
  929. X                    turn = THEIRS;
  930. X                    break;
  931. X                }
  932. X                case '2':{
  933. X                    turn = OURS;
  934. X                    break;
  935. X                }
  936. X            }
  937. X        }
  938. X        argv++;
  939. X    }
  940. X}
  941. X
  942. X
  943. Xvoid
  944. Xdo_scores()
  945. X{
  946. X    register int c;
  947. X
  948. X    open_scorefile("r");
  949. X    while ((c = getc(scorefile)) != EOF)
  950. X        putchar(c);
  951. X}
  952. X
  953. X
  954. Xint
  955. Xcount(w, n, who)
  956. Xwin_list_t *w;
  957. Xu_char n;
  958. Xint who;
  959. X{
  960. X    register u_char *list = who == OURS ? w->us : w->them;
  961. X    register int i;
  962. X    register int total = 0;
  963. X
  964. X    for (i = 0; i < WINS; i++){
  965. X        if (list[i] == n){
  966. X            total++;
  967. X        }
  968. X    }
  969. X
  970. X    return total;
  971. X}
  972. X
  973. Xvoid
  974. Xbell()
  975. X{
  976. X    putchar(7);
  977. X}
  978. X
  979. Xvoid
  980. Xdebug_on()
  981. X{
  982. X    if (d) return;
  983. X    if (save){
  984. X        d = save;
  985. X        fprintf(d, "\n\nDEBUG RESUMED after move %d\n\n", moves_played);
  986. X        report("debug resumed");
  987. X    }
  988. X    else{
  989. X        struct passwd *pwd = getpwnam(wizard);
  990. X        if (!pwd || getuid() != pwd->pw_uid){
  991. X            return;
  992. X        }
  993. X        else{
  994. X            d = fopen("debug", "w");
  995. X            if (!d){
  996. X                report("debug could be started (fopen fails)");
  997. X            }
  998. X            else{
  999. X                fprintf(d, "\n\nDEBUG ON after move %d\n\n", moves_played);
  1000. X                report("debug on");
  1001. X            }
  1002. X        }
  1003. X    }
  1004. X    accept_move(turn);
  1005. X}
  1006. X
  1007. Xvoid
  1008. Xdebug_off()
  1009. X{
  1010. X    if (!d) return;
  1011. X    fprintf(d, "\n\nDEBUG OFF after move %d\n\n", moves_played);
  1012. X    report("debug off");
  1013. X    fflush(d);
  1014. X    save = d;
  1015. X    d = NULL;
  1016. X    accept_move(turn);
  1017. X}
  1018. X
  1019. X/* 
  1020. X * Modify the environment to put message in the right place for
  1021. X * the w and ps commands to find.  Code stolen from MFCF lock
  1022. X * program, originally by Ian!
  1023. X *
  1024. X */
  1025. X
  1026. Xvoid
  1027. Xenvmesg(environ, message)
  1028. Xchar **environ;
  1029. Xchar *message;
  1030. X{
  1031. X    /* 
  1032. X     * Note that this clobbers the environment, so we have to
  1033. X     * do it last, after all the getenv and termcap calls.
  1034. X     */
  1035. X
  1036. X    char *last, *address;
  1037. X    while( environ[1] != 0 ) ++environ;
  1038. X    last = environ[0] + strlen(environ[0]);/* address of '\0' */
  1039. X    last = (char *)((int)last&(~03));/* word boundary */
  1040. X    *(int *)last = 0;       /* clean out last word */
  1041. X    address = last +3 -strlen(message);
  1042. X    address = (char *)((int)address&(~03));/* word boundary */
  1043. X    *(int *)(address-4) = 0;    /* clean out word below */
  1044. X    *(int *)(address-8) = 0;    /* clean out word below */
  1045. X    strcpy( address, message );
  1046. X}
  1047. X
  1048. END_OF_FILE
  1049. if test 18926 -ne `wc -c <'c4.c'`; then
  1050.     echo shar: \"'c4.c'\" unpacked with wrong size!
  1051. fi
  1052. # end of 'c4.c'
  1053. fi
  1054. if test -f 'c4.h' -a "${1}" != "-c" ; then 
  1055.   echo shar: Will not clobber existing file \"'c4.h'\"
  1056. else
  1057. echo shar: Extracting \"'c4.h'\" \(1221 characters\)
  1058. sed "s/^X//" >'c4.h' <<'END_OF_FILE'
  1059. X/*
  1060. X * c4.h
  1061. X *
  1062. X */
  1063. X
  1064. X#define WINS 69
  1065. X#define SQUARES 42
  1066. X#define ROWS 6
  1067. X#define COLUMNS 7
  1068. X
  1069. X#define GAME_OVER -1
  1070. X#define OURS 0
  1071. X#define THEIRS 1
  1072. X#define EMPTY 2
  1073. X#define DRAW 3
  1074. X#define QUIT 4
  1075. X#define CONFUSED 5
  1076. X
  1077. X#define OUR_SYM "+"
  1078. X#define THEIR_SYM "*"
  1079. X#define BLANK_SYM " "
  1080. X
  1081. Xextern char *date();
  1082. Xextern int ask_turn();
  1083. Xextern int count();
  1084. Xextern int get_move();
  1085. Xextern int make();
  1086. Xextern int opportune();
  1087. Xextern int stop();
  1088. Xextern int think_of_fucking_clever_move();
  1089. Xextern int update_column();
  1090. Xextern int update_win_list();
  1091. Xextern void accept_move();
  1092. Xextern void ask_help();
  1093. Xextern void bell();
  1094. Xextern void debug_off();
  1095. Xextern void debug_on();
  1096. Xextern void do_args();
  1097. Xextern void do_scores();
  1098. Xextern void envmesg();
  1099. Xextern void fill_column();
  1100. Xextern void fill_square();
  1101. Xextern void goodbye();
  1102. Xextern void init_board_t();
  1103. Xextern void init_screen();
  1104. Xextern void init_win_list_t();
  1105. Xextern void open_scorefile();
  1106. Xextern void plot_finish();
  1107. Xextern void plot_screen();
  1108. Xextern void print_board();
  1109. Xextern void print_game_record();
  1110. Xextern void print_help();
  1111. Xextern void print_in_what_wins();
  1112. Xextern void report();
  1113. Xextern void reset_row_levels();
  1114. Xextern void show_move();
  1115. Xextern void update_board();
  1116. Xextern void update_game_record();
  1117. END_OF_FILE
  1118. if test 1221 -ne `wc -c <'c4.h'`; then
  1119.     echo shar: \"'c4.h'\" unpacked with wrong size!
  1120. fi
  1121. # end of 'c4.h'
  1122. fi
  1123. if test -f 'screen.c' -a "${1}" != "-c" ; then 
  1124.   echo shar: Will not clobber existing file \"'screen.c'\"
  1125. else
  1126. echo shar: Extracting \"'screen.c'\" \(3076 characters\)
  1127. sed "s/^X//" >'screen.c' <<'END_OF_FILE'
  1128. X#include <stdio.h>
  1129. X#include <curses.h>
  1130. X#include "c4.h"
  1131. X
  1132. X#define  BASEY 0
  1133. X#define  BASEX 0 
  1134. X#define  LINE0  "    0       1       2       3       4       5       6    "
  1135. X#define  LINE1  ".-------------------------------------------------------."
  1136. X#define  LINE2  "|       |       |       |       |       |       |       |"
  1137. X#define  LINE3  "|-------+-------+-------+-------+-------+-------+-------|"
  1138. X#define  LINE4  "`-------------------------------------------------------'"
  1139. X
  1140. Xchar  *filler[] = {"XXXXXXX", "OOOOOOO" };
  1141. X
  1142. Xstatic int row_levels[] = {5, 5, 5, 5, 5, 5, 5};
  1143. X
  1144. Xvoid
  1145. Xinit_screen()
  1146. X{
  1147. X    initscr();
  1148. X    crmode();
  1149. X    noecho();
  1150. X    plot_screen();
  1151. X}
  1152. X
  1153. Xvoid
  1154. Xplot_screen()
  1155. X{
  1156. X    register int i;
  1157. X    register int j;
  1158. X
  1159. X    clear();
  1160. X    move(0,60);
  1161. X    standout();
  1162. X    printw("C O N N E C T   4");
  1163. X    standend();
  1164. X    move(4,60);
  1165. X    printw("  YOUR MOVE:  ");
  1166. X    move(7,60);
  1167. X    printw("    MY MOVE:  ");
  1168. X    move(BASEY,BASEX);
  1169. X    printw(LINE0);
  1170. X    move(BASEY+1,BASEX);
  1171. X    printw(LINE1);
  1172. X    for (i = 0; i < 6; i++){
  1173. X        for (j = 0; j < 2; j++){
  1174. X            move(BASEY + 2 + 3*i + j , BASEX);
  1175. X            printw(LINE2);
  1176. X        }
  1177. X        move(BASEY + 4 + 3*i , BASEX);
  1178. X        printw(LINE3);
  1179. X    }
  1180. X    move(BASEY + 19, BASEX);
  1181. X    printw(LINE4);  
  1182. X    refresh();
  1183. X}
  1184. X
  1185. Xvoid
  1186. Xshow_move(column, who)
  1187. Xint column;
  1188. Xint who;
  1189. X{
  1190. X    int row;
  1191. X    int other_row;
  1192. X
  1193. X    if (who == OURS){
  1194. X        row = 7;
  1195. X        other_row = 4;
  1196. X    }
  1197. X    else{
  1198. X        row = 4;
  1199. X        other_row = 7;
  1200. X    }
  1201. X
  1202. X    move(row, 73);
  1203. X    printw("%1d",column);
  1204. X    move(other_row, 73);
  1205. X    printw(" ");
  1206. X    move(other_row, 73);
  1207. X    refresh();
  1208. X} 
  1209. X
  1210. Xvoid
  1211. Xaccept_move(who)
  1212. Xint who;
  1213. X{
  1214. X    int row;
  1215. X
  1216. X    if (who == OURS)
  1217. X        row = 7;
  1218. X    else
  1219. X        row = 4;
  1220. X
  1221. X    move(row, 73);
  1222. X    printw(" ");
  1223. X    move(row, 73);
  1224. X    refresh();
  1225. X}
  1226. X
  1227. X
  1228. X/* VARARGS1 */
  1229. Xvoid
  1230. Xreport(fmt, a, b, c, d, e, f)
  1231. Xchar *fmt;
  1232. Xchar *a, *b, *c, *d, *e, *f;
  1233. X{
  1234. X    move(22, 0);
  1235. X    printw(fmt, a, b, c, d, e, f);
  1236. X    refresh();
  1237. X}
  1238. X
  1239. Xvoid
  1240. Xplot_finish()
  1241. X{
  1242. X    move(23,0);
  1243. X    refresh();
  1244. X    nocrmode();
  1245. X    echo();
  1246. X}
  1247. X
  1248. X
  1249. Xvoid
  1250. Xfill_column(column, colour)
  1251. Xint column;
  1252. Xint colour;
  1253. X{
  1254. X    register int i;
  1255. X    register int row;
  1256. X
  1257. X    row = row_levels[column];
  1258. X    row_levels[column]--;
  1259. X
  1260. X    for (i = 2; i < 4; i++){
  1261. X        move(BASEY + i + 3*row, BASEX + 1 + 8*column);
  1262. X        if (colour == OURS) {
  1263. X            standout();
  1264. X            printw(filler[colour]);
  1265. X            standend();
  1266. X        }
  1267. X        else{
  1268. X            printw(filler[colour]);
  1269. X        }
  1270. X    }
  1271. X    refresh();
  1272. X}
  1273. X
  1274. Xvoid
  1275. Xfill_square(square, colour)
  1276. Xint square;
  1277. Xint colour;
  1278. X{
  1279. X    register int i;
  1280. X    register int row;
  1281. X    register int column;
  1282. X
  1283. X    row = square / 7;
  1284. X    column = square % 7;
  1285. X
  1286. X    for (i = 2; i < 4; i++){
  1287. X        move(BASEY + i + 3*row, BASEX + 1 + 8*column);
  1288. X        if (colour == OURS) {
  1289. X            standout();
  1290. X            printw(filler[colour]);
  1291. X            standend();
  1292. X        }
  1293. X        else{
  1294. X            printw(filler[colour]);
  1295. X        }
  1296. X    }
  1297. X    refresh();
  1298. X}
  1299. X
  1300. X
  1301. Xvoid
  1302. Xreset_row_levels()
  1303. X{
  1304. X    register int i;
  1305. X
  1306. X    for (i = 0; i < COLUMNS; i++){
  1307. X        row_levels[i] = 5;
  1308. X    }
  1309. X}
  1310. END_OF_FILE
  1311. if test 3076 -ne `wc -c <'screen.c'`; then
  1312.     echo shar: \"'screen.c'\" unpacked with wrong size!
  1313. fi
  1314. # end of 'screen.c'
  1315. fi
  1316. if test -f 'tables.h' -a "${1}" != "-c" ; then 
  1317.   echo shar: Will not clobber existing file \"'tables.h'\"
  1318. else
  1319. echo shar: Extracting \"'tables.h'\" \(7047 characters\)
  1320. sed "s/^X//" >'tables.h' <<'END_OF_FILE'
  1321. Xu_char dist_counts[SQUARES] = {
  1322. X     3,  4,  5,  7,  5,  4,  3,    /* Row 0 */
  1323. X     4,  6,  8, 10,  8,  6,  4,    /* Row 1 */
  1324. X     5,  8, 11, 13, 11,  8,  5,    /* Row 2 */
  1325. X     5,  8, 11, 13, 11,  8,  5,    /* Row 3 */
  1326. X     4,  6,  8, 10,  8,  6,  4,    /* Row 4 */
  1327. X     3,  4,  5,  7,  5,  4,  3     /* Row 5 */
  1328. X};
  1329. X
  1330. Xu_char win_in_what[WINS][4] = {
  1331. X    {  0,  1,  2,  3 },   /* Win  0 */
  1332. X    {  1,  2,  3,  4 },   /* Win  1 */
  1333. X    {  2,  3,  4,  5 },   /* Win  2 */
  1334. X    {  3,  4,  5,  6 },   /* Win  3 */
  1335. X    {  7,  8,  9, 10 },   /* Win  4 */
  1336. X    {  8,  9, 10, 11 },   /* Win  5 */
  1337. X    {  9, 10, 11, 12 },   /* Win  6 */
  1338. X    { 10, 11, 12, 13 },   /* Win  7 */
  1339. X    { 14, 15, 16, 17 },   /* Win  8 */
  1340. X    { 15, 16, 17, 18 },   /* Win  9 */
  1341. X    { 16, 17, 18, 19 },   /* Win 10 */
  1342. X    { 17, 18, 19, 20 },   /* Win 11 */
  1343. X    { 21, 22, 23, 24 },   /* Win 12 */
  1344. X    { 22, 23, 24, 25 },   /* Win 13 */
  1345. X    { 23, 24, 25, 26 },   /* Win 14 */
  1346. X    { 24, 25, 26, 27 },   /* Win 15 */
  1347. X    { 28, 29, 30, 31 },   /* Win 16 */
  1348. X    { 29, 30, 31, 32 },   /* Win 17 */
  1349. X    { 30, 31, 32, 33 },   /* Win 18 */
  1350. X    { 31, 32, 33, 34 },   /* Win 19 */
  1351. X    { 35, 36, 37, 38 },   /* Win 20 */
  1352. X    { 36, 37, 38, 39 },   /* Win 21 */
  1353. X    { 37, 38, 39, 40 },   /* Win 22 */
  1354. X    { 38, 39, 40, 41 },   /* Win 23 */
  1355. X    {  0,  7, 14, 21 },   /* Win 24 */
  1356. X    {  1,  8, 15, 22 },   /* Win 25 */
  1357. X    {  2,  9, 16, 23 },   /* Win 26 */
  1358. X    {  3, 10, 17, 24 },   /* Win 27 */
  1359. X    {  4, 11, 18, 25 },   /* Win 28 */
  1360. X    {  5, 12, 19, 26 },   /* Win 29 */
  1361. X    {  6, 13, 20, 27 },   /* Win 30 */
  1362. X    {  7, 14, 21, 28 },   /* Win 31 */
  1363. X    {  8, 15, 22, 29 },   /* Win 32 */
  1364. X    {  9, 16, 23, 30 },   /* Win 33 */
  1365. X    { 10, 17, 24, 31 },   /* Win 34 */
  1366. X    { 11, 18, 25, 32 },   /* Win 35 */
  1367. X    { 12, 19, 26, 33 },   /* Win 36 */
  1368. X    { 13, 20, 27, 34 },   /* Win 37 */
  1369. X    { 14, 21, 28, 35 },   /* Win 38 */
  1370. X    { 15, 22, 29, 36 },   /* Win 39 */
  1371. X    { 16, 23, 30, 37 },   /* Win 40 */
  1372. X    { 17, 24, 31, 38 },   /* Win 41 */
  1373. X    { 18, 25, 32, 39 },   /* Win 42 */
  1374. X    { 19, 26, 33, 40 },   /* Win 43 */
  1375. X    { 20, 27, 34, 41 },   /* Win 44 */
  1376. X    {  0,  8, 16, 24 },   /* Win 45 */
  1377. X    {  1,  9, 17, 25 },   /* Win 46 */
  1378. X    {  2, 10, 18, 26 },   /* Win 47 */
  1379. X    {  3, 11, 19, 27 },   /* Win 48 */
  1380. X    {  3,  9, 15, 21 },   /* Win 49 */
  1381. X    {  4, 10, 16, 22 },   /* Win 50 */
  1382. X    {  5, 11, 17, 23 },   /* Win 51 */
  1383. X    {  6, 12, 18, 24 },   /* Win 52 */
  1384. X    {  7, 15, 23, 31 },   /* Win 53 */
  1385. X    {  8, 16, 24, 32 },   /* Win 54 */
  1386. X    {  9, 17, 25, 33 },   /* Win 55 */
  1387. X    { 10, 18, 26, 34 },   /* Win 56 */
  1388. X    { 10, 16, 22, 28 },   /* Win 57 */
  1389. X    { 11, 17, 23, 29 },   /* Win 58 */
  1390. X    { 12, 18, 24, 30 },   /* Win 59 */
  1391. X    { 13, 19, 25, 31 },   /* Win 60 */
  1392. X    { 14, 22, 30, 38 },   /* Win 61 */
  1393. X    { 15, 23, 31, 39 },   /* Win 62 */
  1394. X    { 16, 24, 32, 40 },   /* Win 63 */
  1395. X    { 17, 25, 33, 41 },   /* Win 64 */
  1396. X    { 17, 23, 29, 35 },   /* Win 65 */
  1397. X    { 18, 24, 30, 36 },   /* Win 66 */
  1398. X    { 19, 25, 31, 37 },   /* Win 67 */
  1399. X    { 20, 26, 32, 38 }    /* Win 68 */
  1400. X};
  1401. X
  1402. X
  1403. Xu_char in_what_wins[] = {
  1404. X
  1405. X     0, 24, 45, -1,                                          /* Square 0 */
  1406. X     0,  1, 25, 46, -1,                                      /* Square 1 */
  1407. X     0,  1,  2, 26, 47, -1,                                  /* Square 2 */
  1408. X     0,  1,  2,  3, 27, 48, 49, -1,                          /* Square 3 */
  1409. X     1,  2,  3, 28, 50, -1,                                  /* Square 4 */
  1410. X     2,  3, 29, 51, -1,                                      /* Square 5 */
  1411. X     3, 30, 52, -1,                                          /* Square 6 */
  1412. X
  1413. X     4, 24, 31, 53, -1,                                      /* Square 7 */
  1414. X     4,  5, 25, 32, 45, 54, -1,                              /* Square 8 */
  1415. X     4,  5,  6, 26, 33, 46, 49, 55, -1,                      /* Square 9 */
  1416. X     4,  5,  6,  7, 27, 34, 47, 50, 56, 57, -1,              /* Square 10 */
  1417. X     5,  6,  7, 28, 35, 48, 51, 58, -1,                      /* Square 11 */
  1418. X     6,  7, 29, 36, 52, 59, -1,                              /* Square 12 */
  1419. X     7, 30, 37, 60, -1,                                      /* Square 13 */
  1420. X
  1421. X     8, 24, 31, 38, 61, -1,                                  /* Square 14 */
  1422. X     8,  9, 25, 32, 39, 49, 53, 62, -1,                      /* Square 15 */
  1423. X     8,  9, 10, 26, 33, 40, 45, 50, 54, 57, 63, -1,          /* Square 16 */
  1424. X     8,  9, 10, 11, 27, 34, 41, 46, 51, 55, 58, 64, 65, -1,  /* Square 17 */
  1425. X     9, 10, 11, 28, 35, 42, 47, 52, 56, 59, 66, -1,          /* Square 18 */
  1426. X    10, 11, 29, 36, 43, 48, 60, 67, -1,                      /* Square 19 */
  1427. X    11, 30, 37, 44, 68, -1,                                  /* Square 20 */
  1428. X
  1429. X    12, 24, 31, 38, 49, -1,                                  /* Square 21 */
  1430. X    12, 13, 25, 32, 39, 50, 57, 61, -1,                      /* Square 22 */
  1431. X    12, 13, 14, 26, 33, 40, 51, 53, 58, 62, 65, -1,          /* Square 23 */
  1432. X    12, 13, 14, 15, 27, 34, 41, 45, 52, 54, 59, 63, 66, -1,  /* Square 24 */
  1433. X    13, 14, 15, 28, 35, 42, 46, 55, 60, 64, 67, -1,          /* Square 25 */
  1434. X    14, 15, 29, 36, 43, 47, 56, 68, -1,                      /* Square 26 */
  1435. X    15, 30, 37, 44, 48, -1,                                  /* Square 27 */
  1436. X
  1437. X    16, 31, 38, 57, -1,                                      /* Square 28 */
  1438. X    16, 17, 32, 39, 58, 65, -1,                              /* Square 29 */
  1439. X    16, 17, 18, 33, 40, 59, 61, 66, -1,                      /* Square 30 */
  1440. X    16, 17, 18, 19, 34, 41, 53, 60, 62, 67, -1,              /* Square 31 */
  1441. X    17, 18, 19, 35, 42, 54, 63, 68, -1,                      /* Square 32 */
  1442. X    18, 19, 36, 43, 55, 64, -1,                              /* Square 33 */
  1443. X    19, 37, 44, 56, -1,                                      /* Square 34 */
  1444. X
  1445. X    20, 38, 65, -1,                                          /* Square 35 */
  1446. X    20, 21, 39, 66, -1,                                      /* Square 36 */
  1447. X    20, 21, 22, 40, 67, -1,                                  /* Square 37 */
  1448. X    20, 21, 22, 23, 41, 61, 68, -1,                          /* Square 38 */
  1449. X    21, 22, 23, 42, 62, -1,                                  /* Square 39 */
  1450. X    22, 23, 43, 63, -1,                                      /* Square 40 */
  1451. X    23, 44, 64, -1                                           /* Square 41 */
  1452. X};
  1453. X
  1454. Xu_short cum_index[SQUARES] = {
  1455. X      0,   4,   9,  15,  23,  29,  34,  /* Squares  0 to  6 */
  1456. X     38,  43,  50,  59,  70,  79,  86,  /* Squares  7 to 13 */
  1457. X     91,  97, 106, 118, 132, 144, 153,  /* Squares 14 to 20 */
  1458. X    159, 165, 174, 186, 200, 212, 221,  /* Squares 21 to 27 */
  1459. X    227, 232, 239, 248, 259, 268, 275,  /* Squares 28 to 34 */
  1460. X    280, 284, 289, 295, 303, 309, 314   /* Squares 35 to 41 */
  1461. X};
  1462. X
  1463. Xint next_in_col[COLUMNS] = {
  1464. X    35, 36, 37, 38, 39, 40, 41
  1465. X};
  1466. X
  1467. Xint attack_good[] = {
  1468. X    0, 1, 25, 500, 100000
  1469. X};
  1470. X
  1471. Xint defend_good[] = {
  1472. X    0, 1, 20, 400, 10000
  1473. X};
  1474. X
  1475. Xchar *experts[] = {
  1476. X    "tcjones",
  1477. X    "ljpoconnor",
  1478. X    "pjyamamoto",
  1479. X    "gjerawlins",
  1480. X    "jshen",
  1481. X    "rvklassen",
  1482. X    "vlestivill",
  1483. X    "rastroobossc",
  1484. X    ""
  1485. X};
  1486. END_OF_FILE
  1487. if test 7047 -ne `wc -c <'tables.h'`; then
  1488.     echo shar: \"'tables.h'\" unpacked with wrong size!
  1489. fi
  1490. # end of 'tables.h'
  1491. fi
  1492. if test -f 'types.h' -a "${1}" != "-c" ; then 
  1493.   echo shar: Will not clobber existing file \"'types.h'\"
  1494. else
  1495. echo shar: Extracting \"'types.h'\" \(132 characters\)
  1496. sed "s/^X//" >'types.h' <<'END_OF_FILE'
  1497. Xtypedef struct {
  1498. X    u_char us[WINS];
  1499. X    u_char them[WINS];
  1500. X} win_list_t;
  1501. X
  1502. Xtypedef struct {
  1503. X    u_char square[SQUARES];
  1504. X} board_t;
  1505. END_OF_FILE
  1506. if test 132 -ne `wc -c <'types.h'`; then
  1507.     echo shar: \"'types.h'\" unpacked with wrong size!
  1508. fi
  1509. # end of 'types.h'
  1510. fi
  1511. echo shar: End of archive 1 \(of 1\).
  1512. cp /dev/null ark1isdone
  1513. MISSING=""
  1514. for I in 1 ; do
  1515.     if test ! -f ark${I}isdone ; then
  1516.     MISSING="${MISSING} ${I}"
  1517.     fi
  1518. done
  1519. if test "${MISSING}" = "" ; then
  1520.     echo You have the archive.
  1521.     rm -f ark[1-9]isdone
  1522. else
  1523.     echo You still need to unpack the following archives:
  1524.     echo "        " ${MISSING}
  1525. fi
  1526. ##  End of shell archive.
  1527. exit 0
  1528.